<script setup lang="ts">
import { onMounted, ref } from "vue";
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js";
import { OutlinePass } from "three/examples/jsm/postprocessing/OutlinePass.js";
import { OutputPass } from "three/examples/jsm/postprocessing/OutputPass.js";
// import { TextureLoader } from "three";

/* dom */
const container = ref<HTMLDivElement | null>(null);

onMounted(() => {
    init();
});

const init = () => {
    const { clientWidth, clientHeight } = container.value as HTMLDivElement;
    const scene = new THREE.Scene();
    scene.background = new THREE.Color(0x0e4c81);
    const camera = new THREE.PerspectiveCamera(
        75,
        clientWidth / clientHeight,
        1,
        1000
    );
    camera.position.set(0, 0, 20);
    camera.lookAt(0, 0, 0);
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(clientWidth, clientHeight);
    container.value?.appendChild(renderer.domElement);

    // 环境光
    const light = new THREE.AmbientLight(0x404040); // 柔和的白光
    scene.add(light);

    // 坐标辅助器
    // const helper = new THREE.AxesHelper(10);
    // scene.add(helper);

    // 轨道控制器
    const control = new OrbitControls(camera, renderer.domElement);

    initBox(scene);

    const groupSensor: THREE.Group = initSensor(scene);

    // 后期处理
    const effectComposer = new EffectComposer(renderer);
    effectComposer.addPass(new RenderPass(scene, camera));
    const outlinePass = new OutlinePass(
        new THREE.Vector2(clientWidth, clientHeight),
        scene,
        camera
    );
    outlinePass.edgeStrength = 5; // 边框的亮度
    outlinePass.edgeGlow = 1; // 光晕[0,1]
    outlinePass.edgeThickness = 7; // 边框宽度
    outlinePass.pulsePeriod = 0; // 呼吸闪烁的速度
    outlinePass.visibleEdgeColor.set(0x00ffff);
    outlinePass.hiddenEdgeColor.set(0x00ffff);
    outlinePass.selectedObjects = groupSensor.children;

    effectComposer.addPass(outlinePass);
    effectComposer.addPass(new OutputPass());

    function render() {
        control.update();
        camera.updateProjectionMatrix();
        renderer.render(scene, camera);
        effectComposer.render();
        requestAnimationFrame(render);
    }
    render();
};

const initBox = (scene: THREE.Scene) => {
    // 单位米（m）
    const length = 50; // 隧道长度
    const radius = 2; // 隧道半径

    // 地面
    const geoGround = new THREE.PlaneGeometry(
        length + 2,
        (radius + 1) * 2,
        length + 2,
        (radius + 1) * 2
    );
    const materialGround = new THREE.MeshBasicMaterial({
        color: 0xaaaaaa,
    });

    const ground = new THREE.Mesh(geoGround, materialGround);
    ground.rotateX(-Math.PI / 2);
    scene.add(ground);

    // 桥洞
    const geoTunnel = new THREE.CylinderGeometry(
        radius,
        radius,
        length,
        8,
        1,
        true
    );
    const materialTunnel = new THREE.MeshBasicMaterial({
        color: 0xbbbbbb,
        side: THREE.BackSide,
    });
    const tunnel = new THREE.Mesh(geoTunnel, materialTunnel);
    tunnel.rotateZ(Math.PI / 2);
    tunnel.rotateY(Math.PI / 8);
    tunnel.position.setY(0.9);
    scene.add(tunnel);

    // 管道
    const geoPipe = new THREE.CylinderGeometry(0.3, 0.3, length + 2);
    const materialPipe1 = new THREE.MeshBasicMaterial({ color: "#ed4014" });
    const materialPipe2 = new THREE.MeshBasicMaterial({ color: "#ff9900" });
    const materialPipe3 = new THREE.MeshBasicMaterial({ color: "#2db7f5" });
    const pipe1 = new THREE.Mesh(geoPipe, materialPipe1);
    const pipe2 = new THREE.Mesh(geoPipe, materialPipe2);
    const pipe3 = new THREE.Mesh(geoPipe, materialPipe3);
    pipe1.position.setZ(-0.8);
    pipe3.position.setZ(0.8);
    const groupPipe = new THREE.Group();
    groupPipe.add(pipe1);
    groupPipe.add(pipe2);
    groupPipe.add(pipe3);
    groupPipe.rotateZ(Math.PI / 2);
    scene.add(groupPipe);
};

const initSensor = (scene: THREE.Scene): THREE.Group => {
    const sensorList = [
        {
            x: -20,
            y: 2.6,
            z: 0,
            name: "环境监测传感器",
        },
        {
            x: 20,
            y: 2.6,
            z: 0,
            name: "环境监测传感器",
        },
        // {
        //     x: 0,
        //     y: 0,
        //     z: 0,
        //     name: "",
        // },
    ];
    const groupSensor = new THREE.Group();

    const geoSensor = new THREE.BoxGeometry(0.1, 0.1, 0.1);
    const materialSensor = new THREE.MeshBasicMaterial({ color: 0x999999 });

    sensorList.forEach((item) => {
        const { x, y, z } = item;
        const sensor = new THREE.Mesh(geoSensor, materialSensor);
        sensor.position.set(x, y, z);
        groupSensor.add(sensor);
    });

    scene.add(groupSensor);

    return groupSensor;
};
</script>

<template>
    <div ref="container" class="container"></div>
</template>

<style lang="less" scoped>
.container {
    width: 100%;
    height: 100%;
}
</style>
